package com.informatics.polymer.server;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

import org.apache.commons.io.FileUtils;
import org.restlet.Context;
import org.restlet.data.Form;
import org.restlet.data.MediaType;
import org.restlet.data.Request;
import org.restlet.data.Response;
import org.restlet.data.Status;
import org.restlet.resource.Representation;
import org.restlet.resource.Resource;
import org.restlet.resource.ResourceException;
import org.restlet.resource.StringRepresentation;
import org.restlet.resource.Variant;

import com.informatics.polymer.server.Polymerisation.BlockCopolymerisation;
import com.informatics.polymer.server.Polymerisation.GraftCopolymerisation;
import com.informatics.polymer.server.Polymerisation.PolymerisationUtils;
/**
 * Restlet to implement graft copolymerization, it takes parameters from the GWT GUI then builds the
 * polymer using the polymerization API and returns the resultant XML to JMol for viewing.
 * @author ed
 * @version 1.0
 */

public class GraftCopolymerBuilder extends Resource {
	/**
	 * String representation of endGroup1.
	 */
	private String eg1;
	/**
	 * String representation of the repeat unit A.
	 */
	private String repeatUnitMainChain;
	/**
	 * String representation of repeat unit B.
	 */
	private String repeatUnitBranchChain;
	/**
	 * String representation of endGroup2.
	 */
	private String endGroup2;
	/**
	 * Integer value for the degree of polymerisation.
	 */
	private int degreeOfPolymerisationMainChain;
	/**
	 * Integer value for the degree of polymerisation of repeat unit B.
	 */
	private int degreeOfPolymerisationBranchChain;
	//Getters and setters.
	/**
	 * Sets degree of polymerisation of repeat unit B.
	 */
	private void setDegreeOfPolymerisationBranchChain(int val){
		this.degreeOfPolymerisationBranchChain = val;
	}
	/**
	 * Gets degree of  polymerisation B.
	 * @return integer representing the degree of polymerisation of repeat unit B.
	 */
	private int getDegreeOfPolymerisationBranchChain(){
		return this.degreeOfPolymerisationBranchChain;
	}
	/**
	 * Sets endGroup1 value.
	 */
	private void setEG1(String val){
		this.eg1 = val;
	}
	/**
	 * Gets endGroup1.
	 * @return String representation of endGroup1.
	 */
	private String getEG1(){
		return eg1;
	}
	/**
	 * Sets the repeat unit.
	 * @param repeatUnitValue - String representation of the repeat unit.
	 */
	private void setRepeatUnit(String repeatUnitValue){
		this.repeatUnitMainChain = repeatUnitValue;
	}
	/**
	 * Gets repeat unit.
	 * @return String representation of the repeat unit.
	 */
	private String getRepeatUnit(){
		return repeatUnitMainChain;
	}
	/**
	 * Sets repeat unit B.
	 * @param repeatUnitValue - String representation of repeat unit B.
	 */
	private void setRepeatUnitBranchChain(String repeatUnitValue){
		this.repeatUnitBranchChain = repeatUnitValue;
	}
	/**
	 * Gets repeat unit B.
	 * @return String representation of repeat unit B.
	 */
	private String getRepeatUnitBranchChain(){
		return repeatUnitBranchChain;
	}
	/**
	 * Sets endGroup2.
	 * @param endGroup2 - String representation of endGroup2.
	 */
	private void setEndGroup2(String endGroup2){
		this.endGroup2 = endGroup2;
	}
	/**
	 * Gets endGroup2.
	 * @return String representation of endGroup2.
	 */
	private String getEndGroup2(){
		return endGroup2;
	}
	/**
	 * Sets the degree of polymerisation.
	 * @param dp - integer value representing the number of repeat units in a polymerisation.
	 */
	private void setDegreeOfPolymerisationMainChain(int dp){
		this.degreeOfPolymerisationMainChain = dp;
	}
	/**
	 * Gets degree of polymerisation.
	 * @return Integer value representing the degree of polymerisation.
	 */
	private int getDegreeOfPolymerisationMainChain(){
		return degreeOfPolymerisationMainChain;
	}

	/**
	 * Initiate the restlet.
	 */
	public void init(Context context, Request request, Response response) {
		super.init(context, request, response);
	//	getVariants().add(Constants.XML_VARIANT);
		getVariants().add(new Variant(MediaType.TEXT_PLAIN));
		this.setModifiable(true);
	}
	/**
	 * Method allows forms to be posted to restlet.
	 */
	@Override
	public boolean allowPost() {
		return true;
	}

	/**
	 * Constructs Block copolymerBuilder resource.
	 * @param context 
	 * @param request
	 * @param response
	 */
	public GraftCopolymerBuilder(Context context, Request request, Response response){
		super(context,request,response);
		getVariants().add(new Variant(MediaType.TEXT_PLAIN));
	}

	/**
	 * Method deals with the form posted to the restlet.
	 */
	@Override
	public void post(Representation entity) {
		// Get the URLs and polymerisation parameters from the request (getRequest)
		Form form = new Form(entity); 
		setEG1(form.getValues("endGroup1"));
		setRepeatUnit(form.getValues("repeatUnit"));
		setRepeatUnitBranchChain(form.getValues("repeatUnitBranch"));
		setEndGroup2(form.getValues("endGroup2"));
		setDegreeOfPolymerisationBranchChain(Integer.parseInt(form.getValues("degreeOfPolymerisationBranch")));
		setDegreeOfPolymerisationMainChain(Integer.parseInt(form.getValues("degreeOfPolymerisationMain")));
		String counterValue =  form.getValues("counter");
		GraftCopolymerisation graftCopolymerisation = new GraftCopolymerisation(getDegreeOfPolymerisationMainChain(),getDegreeOfPolymerisationBranchChain(),
				getEG1(), getRepeatUnit(),getRepeatUnitBranchChain(),getEndGroup2());
		String graftCopolymerNoCoords = graftCopolymerisation.getPolymer().toXML();
		String polymerWith3DCoords = null;
		try {
			polymerWith3DCoords = PolymerisationUtils.add3DCoordinates(graftCopolymerNoCoords);
		} catch (Exception e) {
			e.printStackTrace();
		}
		String finalResult = polymerWith3DCoords;
		StringRepresentation str = new StringRepresentation(finalResult);
		//Write out to a file
		String f = "/GraftCopolymer"+counterValue+".cml";
		String curDir = new String(System.getProperty("user.dir"));
		File graftpolymerXml = new File(curDir+f);
		BufferedWriter out;
		//Use apache io
		try {
			FileUtils.writeStringToFile(graftpolymerXml, finalResult);
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		try {
			out = new BufferedWriter(new FileWriter(curDir+f));
			out.write(finalResult);
		    out.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
       
		getResponse().setEntity(str);
	}

	// Respond to GET
	public Representation represent (Variant variant) throws ResourceException{
		Representation resource = null;
			if (!MediaType.TEXT_PLAIN.includes(variant.getMediaType())) {
				throw new ResourceException(Status.CLIENT_ERROR_NOT_ACCEPTABLE);
			}
			else{
				StringBuffer sb = new StringBuffer();
				try {
					sb.append(":");
					sb.append(":");
					sb.append(getEndGroup2());
				} catch (Exception e) {
					e.printStackTrace();
				}		
				resource = new StringRepresentation(sb.toString(), MediaType.TEXT_PLAIN); 
				return resource;
			}
	}


}
